import json
import asyncio
import datetime
from pathlib import Path
from typing import List, Tuple, Union

from PIL import Image, ImageDraw
from gsuid_core.logger import logger
from gsuid_core.utils.image.image_tools import (
    get_color_bg,
    get_qq_avatar,
    draw_pic_with_ring,
)

from ..utils.image.convert import convert_img
from ..utils.map.name_covert import name_to_avatar_id, name_to_weapon_id
from ..utils.resource.RESOURCE_PATH import (
    PLAYER_PATH,
    WEAPON_PATH,
    CHAR_ICON_PATH,
)
from ..utils.fonts.starrail_fonts import (
    sr_font_20,
    sr_font_24,
    sr_font_28,
    sr_font_38,
    sr_font_40,
)

TEXT_PATH = Path(__file__).parent / 'texture2d'
EMO_PATH = Path(__file__).parent / 'texture2d' / 'emo'

# up_tag = Image.open(TEXT_PATH / 'up.png')
Abg3_img = Image.open(TEXT_PATH / 'Abg3.png')
bg1_img = Image.open(TEXT_PATH / 'bg1.png')

first_color = (29, 29, 29)
brown_color = (41, 25, 0)
red_color = (255, 66, 66)
green_color = (74, 189, 119)
white_color = (213, 213, 213)
whole_white_color = (255, 255, 255)

CHANGE_MAP = {
    '始发跃迁': 'begin',
    '群星跃迁': 'normal',
    '角色跃迁': 'char',
    '光锥跃迁': 'weapon',
}
HOMO_TAG = ['非到极致', '运气不好', '平稳保底', '小欧一把', '欧狗在此']
NORMAL_LIST = [
    '彦卿',
    '白露',
    '姬子',
    '瓦尔特',
    '布洛妮娅',
    '克拉拉',
    '杰帕德',
    '银河铁道之夜',
    '以世界之名',
    '但战斗还未结束',
    '制胜的瞬间',
    '无可取代的东西',
    '时节不居',
    '如泥酣眠',
]

UP_LIST = {
    '刻晴': [(2021, 2, 17, 18, 0, 0), (2021, 3, 2, 15, 59, 59)],
    '提纳里': [(2022, 8, 24, 11, 0, 0), (2022, 9, 9, 17, 59, 59)],
    '迪希雅': [(2023, 3, 1, 11, 0, 0), (2023, 3, 21, 17, 59, 59)],
}


async def _draw_card(
    img: Image.Image,
    xy_point: Tuple[int, int],
    card_type: str,
    name: str,
    gacha_num: int,
    is_up: bool,
):
    card_img = Image.open(TEXT_PATH / 'char_bg.png')
    card_img_draw = ImageDraw.Draw(card_img)
    point = (47, 31)
    text_point = (100, 165)
    if card_type == '角色':
        _id = await name_to_avatar_id(name)
        item_pic = (
            Image.open(CHAR_ICON_PATH / f'{_id}.png')
            .convert('RGBA')
            .resize((105, 105))
        )
    else:
        name = await name_to_weapon_id(name)
        # _id = await weapon_id_to_en_name(name)
        item_pic = (
            Image.open(WEAPON_PATH / f'{name}.png')
            .convert('RGBA')
            .resize((124, 124))
        )
        point = (37, 24)
    card_img.paste(item_pic, point, item_pic)
    if gacha_num >= 81:
        text_color = red_color
    elif gacha_num <= 55:
        text_color = green_color
    else:
        text_color = brown_color
    card_img_draw.text(
        text_point, f'{gacha_num}抽', text_color, sr_font_24, 'mm'
    )
    if is_up:
        logger.info(f'up: {name}')
        # card_img.paste(up_tag, (47, -2), up_tag)
    img.paste(card_img, xy_point, card_img)


async def random_emo_pic(level: int) -> Image.Image:
    emo_fold = EMO_PATH / f'3000{level}.png'
    return Image.open(emo_fold)


async def get_level_from_list(ast: int, lst: List) -> int:
    if ast == 0:
        return 3

    for num_index, num in enumerate(lst):
        if ast <= num:
            level = num_index + 1
            break
    else:
        level = 6
    return level


def check_up(name: str, _time: str) -> bool:
    for char in UP_LIST:
        if char == name:
            time = UP_LIST[char]
            s_time = datetime.datetime(*time[0])
            e_time = datetime.datetime(*time[1])
            gacha_time = datetime.datetime.strptime(_time, '%Y-%m-%d %H:%M:%S')
            if gacha_time < s_time or gacha_time > e_time:
                return False
            return True
    return False


async def draw_gachalogs_img(uid: str, user_id: str) -> Union[bytes, str]:
    path = PLAYER_PATH / str(uid) / 'gacha_logs.json'
    if not path.exists():
        return '你还没有跃迁数据噢~\n请使用命令`sr导入抽卡链接`更新跃迁数据~'
    with Path.open(path, encoding='UTF-8') as f:
        gacha_data = json.load(f)

    # 数据初始化
    total_data = {}
    for i in ['群星跃迁', '始发跃迁', '角色跃迁', '光锥跃迁']:
        total_data[i] = {
            'total': 0,  # 五星总数
            'avg': 0,  # 抽卡平均数
            'avg_up': 0,  # up平均数
            'remain': 0,  # 已xx抽未出金
            'r_num': [],  # 不包含首位的抽卡数量
            'e_num': [],  # 包含首位的up抽卡数量
            'up_list': [],  # 抽到的UP列表(不包含首位)
            'normal_list': [],  # 抽到的五星列表(不包含首位)
            'list': [],  # 抽到的五星列表
            'time_range': '',  # 抽卡时间
            'all_time': 0,  # 抽卡总计秒数
            'type': '一般型',  # 抽卡类型: 随缘型, 氪金型, 规划型, 仓鼠型, 佛系型
            'short_gacha_data': {'time': 0, 'num': 0},
            'long_gacha_data': {'time': 0, 'num': 0},
        }
        # 拿到数据列表
        data_list = gacha_data['data'][i]
        # 初始化开关
        is_not_first = True
        # 开始初始化抽卡数
        num = 1
        # 从后面开始循环
        temp_time = datetime.datetime(2023, 4, 26, 8, 0, 0)
        for index, data in enumerate(data_list[::-1]):
            # 计算抽卡时间跨度
            if index == 0:
                total_data[i]['time_range'] = data['time']
            if index == len(data_list) - 1:
                total_data[i]['all_time'] = (
                    datetime.datetime.strptime(
                        data['time'], '%Y-%m-%d %H:%M:%S'
                    )
                    - datetime.datetime.strptime(
                        total_data[i]['time_range'], '%Y-%m-%d %H:%M:%S'
                    )
                ).total_seconds()
                total_data[i]['time_range'] += '~' + data['time']

            # 计算时间间隔
            if index != 0:
                now_time = datetime.datetime.strptime(
                    data['time'], '%Y-%m-%d %H:%M:%S'
                )
                dis = (now_time - temp_time).total_seconds()
                temp_time = now_time
                if dis <= 5000:
                    total_data[i]['short_gacha_data']['num'] += 1
                    total_data[i]['short_gacha_data']['time'] += dis
                elif dis >= 86400:
                    total_data[i]['long_gacha_data']['num'] += 1
                    total_data[i]['long_gacha_data']['time'] += dis
            else:
                temp_time = datetime.datetime.strptime(
                    data['time'], '%Y-%m-%d %H:%M:%S'
                )

            # 如果这是个五星
            if data['rank_type'] == '5':
                # 抽到这个五星花了多少抽
                data['gacha_num'] = num

                # 判断是否是UP
                if data['name'] in NORMAL_LIST:
                    data['is_up'] = False
                elif data['name'] in UP_LIST:
                    data['is_up'] = check_up(data['name'], data['time'])
                else:
                    data['is_up'] = True

                # 往里加东西
                if is_not_first:
                    total_data[i]['r_num'].append(num)
                    total_data[i]['normal_list'].append(data)
                    if data['is_up']:
                        total_data[i]['up_list'].append(data)

                # 把这个数据扔到抽到的五星列表内
                total_data[i]['list'].append(data)

                # 判断经过了第一个
                if total_data[i]['list']:
                    is_not_first = True

                num = 1
                # 五星总数增加1
                total_data[i]['total'] += 1
            else:
                num += 1

        # 计算已多少抽
        total_data[i]['remain'] = num - 1

        # 计算平均抽卡数
        if len(total_data[i]['normal_list']) == 0:
            total_data[i]['avg'] = 0
        else:
            total_data[i]['avg'] = float(
                '{:.2f}'.format(
                    sum(total_data[i]['r_num']) / len(total_data[i]['r_num'])
                )
            )
        # 计算平均up数量
        if len(total_data[i]['up_list']) == 0:
            total_data[i]['avg_up'] = 0
        else:
            total_data[i]['avg_up'] = float(
                '{:.2f}'.format(
                    sum(total_data[i]['r_num']) / len(total_data[i]['up_list'])
                )
            )

        # 计算抽卡类型
        # 如果抽卡总数小于40
        if gacha_data[f'{CHANGE_MAP[i]}_gacha_num'] <= 40:
            total_data[i]['type'] = '佛系型'
        # 如果长时抽卡总数占据了总抽卡数的70%
        elif (
            total_data[i]['long_gacha_data']['num']
            / gacha_data[f'{CHANGE_MAP[i]}_gacha_num']
            >= 0.7
        ):
            total_data[i]['type'] = '随缘型'
        # 如果短时抽卡总数占据了总抽卡数的70%
        elif (
            total_data[i]['short_gacha_data']['num']
            / gacha_data[f'{CHANGE_MAP[i]}_gacha_num']
            >= 0.7
        ):
            total_data[i]['type'] = '规划型'
        # 如果抽卡数量远远大于标称抽卡数量
        elif (
            total_data[i]['all_time'] / 30000
            <= gacha_data[f'{CHANGE_MAP[i]}_gacha_num']
        ):
            # 如果长时抽卡数量大于短时抽卡数量
            if (
                total_data[i]['long_gacha_data']['num']
                >= total_data[i]['short_gacha_data']['num']
            ):
                total_data[i]['type'] = '规划型'
            else:
                total_data[i]['type'] = '氪金型'
        # 如果抽卡数量远远小于标称抽卡数量
        elif (
            total_data[i]['all_time'] / 32000
            >= gacha_data[f'{CHANGE_MAP[i]}_gacha_num'] * 2
        ):
            total_data[i]['type'] = '仓鼠型'

    # 常量偏移数据
    single_y = 170

    # 计算图片尺寸
    normal_y = (1 + ((total_data['群星跃迁']['total'] - 1) // 5)) * single_y
    begin_y = (1 + ((total_data['始发跃迁']['total'] - 1) // 5)) * single_y
    char_y = (1 + ((total_data['角色跃迁']['total'] - 1) // 5)) * single_y
    weapon_y = (1 + ((total_data['光锥跃迁']['total'] - 1) // 5)) * single_y

    # 获取背景图片各项参数
    _id = str(user_id)
    if _id.startswith('http'):
        char_pic = await get_qq_avatar(avatar_url=_id)
    else:
        char_pic = await get_qq_avatar(qid=user_id)
    char_pic = await draw_pic_with_ring(char_pic, 206, None, False)

    # 获取背景图片各项参数
    img = Abg3_img.copy()
    img = await get_color_bg(
        800, 1600 + 400 + normal_y + char_y + weapon_y + begin_y
    )
    gacha_title = bg1_img.copy()
    gacha_title.paste(char_pic, (297, 81), char_pic)
    img.paste(gacha_title, (0, 0), gacha_title)
    img_draw = ImageDraw.Draw(img)
    img_draw.text((400, 345), f'UID {uid}', white_color, sr_font_28, 'mm')

    # 处理title
    # {'total': 0, 'avg': 0, 'remain': 0, 'list': []}
    type_list = ['角色跃迁', '光锥跃迁', '群星跃迁', '始发跃迁']
    y_extend = 0
    level = 3
    for index, i in enumerate(type_list):
        title = Image.open(TEXT_PATH / 'bg2.png')
        if i == '群星跃迁':
            level = await get_level_from_list(
                total_data[i]['avg'], [54, 61, 67, 73, 80]
            )
        elif i == '始发跃迁':
            level = await get_level_from_list(
                total_data[i]['avg'], [10, 20, 30, 40, 50]
            )
        elif i == '光锥跃迁':
            level = await get_level_from_list(
                total_data[i]['avg_up'], [62, 75, 88, 99, 111]
            )
        else:
            level = await get_level_from_list(
                total_data[i]['avg_up'], [74, 87, 99, 105, 120]
            )

        emo_pic = await random_emo_pic(level)
        emo_pic = emo_pic.resize((195, 195))
        title.paste(emo_pic, (500, 123), emo_pic)
        title_draw = ImageDraw.Draw(title)
        # 卡池
        title_draw.text((110, 73), i, whole_white_color, sr_font_38, 'lm')
        # 抽卡时间
        if total_data[i]['time_range']:
            time_range = total_data[i]['time_range']
        else:
            time_range = '暂未抽过卡!'
        title_draw.text((78, 340), time_range, brown_color, sr_font_20, 'lm')
        # 平均抽卡数量
        title_draw.text(
            (143, 215),
            str(total_data[i]['avg']),
            first_color,
            sr_font_40,
            'mm',
        )
        # 平均up
        title_draw.text(
            (280, 215),
            str(total_data[i]['avg_up']),
            first_color,
            sr_font_40,
            'mm',
        )
        # 抽卡总数
        title_draw.text(
            (413, 215),
            str(gacha_data[f'{CHANGE_MAP[i]}_gacha_num']),
            first_color,
            sr_font_40,
            'mm',
        )
        # 已抽数
        title_draw.text(
            (333, 75),
            str(total_data[i]['remain']),
            red_color,
            sr_font_28,
            'mm',
        )
        y_extend += (
            (1 + ((total_data[type_list[index - 1]]['total'] - 1) // 5))
            * single_y
            if index != 0
            else 0
        )
        y = 350 + index * 400 + y_extend
        img.paste(title, (0, y), title)
        tasks = []
        for item_index, item in enumerate(total_data[i]['list']):
            item_x = (item_index % 5) * 138 + 25
            item_y = (item_index // 5) * single_y + y + 355
            xy_point = (item_x, item_y)
            tasks.append(
                _draw_card(
                    img,
                    xy_point,
                    item['item_type'],
                    item['name'],
                    item['gacha_num'],
                    item['is_up'],
                )
            )
        await asyncio.gather(*tasks)
        tasks.clear()

    # 发送图片
    res = await convert_img(img)
    logger.info('[查询抽卡]绘图已完成,等待发送!')
    # res = 123
    return res
